﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Randomize
{
    class Program
    {
        public static Random rnd = new Random();

        static void Main(string[] args)
        {
            RandomSubset(50, 25000, 60000);
        }

        public static int[][] RandomSubset(int numTree, int numRecordsEachTree, int numRecords)
        {
            int[] indexes = new int[numTree];
            int[][] rVal = new int[numTree][];

            for (int i = 0; i < rVal.Length; i++)
                rVal[i] = new int[numRecordsEachTree];

            for (int i = 0; i < numRecordsEachTree; i++)
            {
                for (int j = 0; j < numTree; j++)
                {
                    int temp = (i*numTree + j) % numRecordsEachTree;
                    if (!rVal[j].Contains(temp))
                    {
                        rVal[j][indexes[j]] = temp;
                        indexes[j]++;
                    }
                }
            }

            return rVal;
        }


        public static int[][] RandomSubsetA(int numTree, int numRecordsEachTree, int numRecords) //does not check if the tree has the character already
        {
            int[][] rVal = new int[numTree][];
            int requiredDataset = Convert.ToInt32(Math.Ceiling(Convert.ToDouble((numTree * numRecordsEachTree) / numRecords))); // numRecordList count to be used to fill the trees
            List<int> numRecordsList = new List<int>();

            for (int i = 0; i < numRecords; i++) { numRecordsList.Add(i); }//Make numRecords list so that the used index will be removed

            for (int i = 0; i < rVal.Length; i++) { rVal[i] = new int[numRecordsEachTree]; }//rVal second dimension = 20000

            for (int i = 0; i < numRecordsEachTree; i++)//import indexes to the rVal,count = 20000
            {
                for (int j = 0; j < rVal.Length; j++)//for every tree, count 50
                {
                    int chosenIndex = rnd.Next(0, numRecordsList.Count);// chose random index 0-list count
                    rVal[j][i] = numRecordsList[chosenIndex];//import random index
                    numRecordsList.Remove(chosenIndex);//remove random index not to be picked again

                    if (numRecordsList.Count == 0 && requiredDataset > 0)//if numRecordList is not enough refresh it 
                    {
                        for (int k = 0; k < numRecords; k++) { numRecordsList.Add(k); }
                        requiredDataset--;
                    }
                }
            }
            return rVal;
        }

        public static int[][] RandomSubsetB(int numTree, int numRecordsEachTree, int numRecords)//Algorith 2 
        {
            int[][] rVal = new int[numTree][];
            int requiredWholeDataset = Convert.ToInt32(Math.Floor(Convert.ToDouble((numTree * numRecordsEachTree) / numRecords))); // numRecordList count to be used to fill the trees
            int addRequiredDataset = (numTree * numRecordsEachTree) - (numRecords * requiredWholeDataset);// additional characters for dataset

            List<int> numRecordsList = new List<int>();
            List<int> numRecordsListAppend = new List<int>();

            for (int i = 0; i < numRecords; i++) { numRecordsListAppend.Add(i); }

            for (int i = 0; i < requiredWholeDataset; i++) //Make numRecords list so that the used index will be removed, numRecordList count = 996.000 
            {
                for (int j = 0; j < numRecords; j++)
                {
                    numRecordsList.Add(j);
                }
            }

            for (int i = 0; i < addRequiredDataset; i++)// add the additional character Indexes to the numRecordList, numRecordList count = 1.000.000
            {
                int chosenIndexNumRecordList = rnd.Next(0, numRecordsListAppend.Count);// chose random index 0-numRecords
                numRecordsList.Add(numRecordsListAppend[chosenIndexNumRecordList]);
                numRecordsListAppend.Remove(chosenIndexNumRecordList);

            }

            for (int i = 0; i < rVal.Length; i++) { rVal[i] = new int[numRecordsEachTree]; }//rVal second dimension = 20000

            for (int i = 0; i < numRecordsEachTree; i++)//import indexes to the rVal,count = 20000
            {
                for (int j = 0; j < rVal.Length; j++)//for every tree, count 50
                {
                    int sameAgain = 0;

                    while (true)
                    {
                        int chosenIndex = rnd.Next(0, numRecordsList.Count);// chose random index 0-list count

                        if (rVal[j].Contains(numRecordsList[chosenIndex])) { sameAgain++; }

                        if (sameAgain > 9)
                        {
                            rVal[j][i] = numRecordsList[chosenIndex];//import random index
                            numRecordsList.Remove(chosenIndex);//remove random index not to be picked again

                            break;
                        }

                        if (!(rVal[j].Contains(numRecordsList[chosenIndex])))
                        {
                            rVal[j][i] = numRecordsList[chosenIndex];//import random index
                            numRecordsList.Remove(chosenIndex);//remove random index not to be picked again

                            break;
                        }
                    }
                }
            }
            return rVal;
        }

        public static int[][] RandomSubsetC(int numTree, int numRecordsEachTree, int numRecords)//Algorithm 3
        {
            int[][] rVal = new int[numTree][];
            int requiredWholeDataset = Convert.ToInt32(Math.Floor(Convert.ToDouble((numTree * numRecordsEachTree) / numRecords))); // numRecordList count to be used to fill the trees
            int addRequiredDataset = (numTree * numRecordsEachTree) - (numRecords * requiredWholeDataset);// additional characters for dataset

            List<int> numRecordsList = new List<int>();
            List<int> numRecordsListAppend = new List<int>();

            for (int i = 0; i < numRecords; i++) { numRecordsListAppend.Add(i); }

            for (int i = 0; i < requiredWholeDataset; i++) //Make numRecords list so that the used index will be removed, numRecordList count = 960.000 
            {
                for (int j = 0; j < numRecords; j++)
                {
                    numRecordsList.Add(j);
                }
            }

            for (int i = 0; i < rVal.Length; i++) { rVal[i] = new int[numRecordsEachTree]; }//rVal second dimension = 20000

            for (int i = 0; i < numRecordsEachTree; i++)//import indexes to the rVal,count = 20000
            {
                for (int j = 0; j < rVal.Length; j++)//for every tree, count 50
                {
                    int sameAgain = 0;

                    while (true)
                    {
                        int chosenIndex = rnd.Next(0, numRecordsList.Count);// chose random index 0-list count

                        if (rVal[j].Contains(numRecordsList[chosenIndex])) { sameAgain++; }

                        if (sameAgain > 9)
                        {
                            rVal[j][i] = numRecordsList[chosenIndex];//import random index
                            numRecordsList.Remove(chosenIndex);//remove random index not to be picked again

                            break;
                        }

                        if (!(rVal[j].Contains(numRecordsList[chosenIndex])))
                        {
                            rVal[j][i] = numRecordsList[chosenIndex];//import random index
                            numRecordsList.Remove(chosenIndex);//remove random index not to be picked again

                            break;
                        }

                    }
                }
            }

            for (int i = ((requiredWholeDataset * numRecords) / numTree); i < numRecordsEachTree; i++)//import indexes to the rVal,count = 20000-the amount that is already in.
            {
                for (int j = 0; j < rVal.Length; j++)//for every tree, count 50
                {
                    int chosenIndex = rnd.Next(0, numRecordsListAppend.Count);// chose random index 0-list count

                    rVal[j][i] = numRecordsListAppend[chosenIndex];//import random index
                    numRecordsListAppend.Remove(chosenIndex);//remove random index not to be picked again
                }
            }
            return rVal;
        }

        public static int[][] RandomSubsetD(int numTree, int numRecordsEachTree, int numRecords)//does not check if the tree has the character already
        {
            int[][] rVal = new int[numTree][];
            int requiredWholeDataset = Convert.ToInt32(Math.Floor(Convert.ToDouble((numTree * numRecordsEachTree) / numRecords))); // numRecordList count to be used to fill the trees
            int addRequiredDataset = (numTree * numRecordsEachTree) - (numRecords * requiredWholeDataset);

            List<int> numRecordsList = new List<int>();
            List<int> numRecordsListAppend = new List<int>();

            for (int i = 0; i < numRecords; i++) { numRecordsListAppend.Add(i); }

            for (int i = 0; i < numRecords; i++) { numRecordsList.Add(i); }//Make numRecords list so that the used index will be removed

            for (int i = 0; i < rVal.Length; i++) { rVal[i] = new int[numRecordsEachTree]; }//rVal second dimension = 20000

            for (int i = 0; i < numRecordsEachTree; i++)//import indexes to the rVal,count = 20000
            {
                for (int j = 0; j < rVal.Length; j++)//for every tree, count 50
                {
                    int sameAgain = 0;
                    while (true)
                    {
                        if (numRecordsList.Count == 0 && requiredWholeDataset > 0)//if numRecordList is not enough refresh it 
                        {
                            for (int k = 0; k < numRecords; k++) { numRecordsList.Add(k); }
                            requiredWholeDataset--;
                        }

                        int chosenIndex = rnd.Next(0, numRecordsList.Count);// chose random index 0-list count

                        if (rVal[j].Contains(numRecordsList[chosenIndex])) { sameAgain++; }

                        if (sameAgain > 9)
                        {
                            rVal[j][i] = numRecordsList[chosenIndex];//import random index
                            numRecordsList.Remove(chosenIndex);//remove random index not to be picked again

                            break;
                        }

                        if (!(rVal[j].Contains(numRecordsList[chosenIndex])))
                        {
                            rVal[j][i] = numRecordsList[chosenIndex];//import random index
                            numRecordsList.Remove(chosenIndex);//remove random index not to be picked again

                            break;
                        }

                    }
                }
            }

            for (int i = ((requiredWholeDataset * numRecords) / numTree); i < numRecordsEachTree ; i++)//import indexes to the rVal,count = 20000-the amount that is already in.
            {
                for (int j = 0; j < rVal.Length; j++)//for every tree, count 50
                {
                    int chosenIndex = rnd.Next(0, numRecordsListAppend.Count);// chose random index 0-list count

                    rVal[j][i] = numRecordsListAppend[chosenIndex];//import random index
                    numRecordsListAppend.Remove(chosenIndex);//remove random index not to be picked again
                }
            }

            return rVal;
        }
    }
}
